﻿// ----------------------------------------------------------------------------------
// Sample Code from Fernando Machado Píriz's blog: http://fernandomachadopiriz.com
//
// <copyright company="Fernando Machado Píriz" file="ExceptionHelper.cs">
// Copyright (c) Fernando Machado Píriz. Distributed under FSF's GPL v2.</copyright>
// ----------------------------------------------------------------------------------
// This code and information are provided "as is" without warranty of any kind,
// either expressed of implied, including but not limited to the implied warranties
// of merchantability and/or fitness for a particular purpose.
// ----------------------------------------------------------------------------------
namespace GivingAPresentation.Commons
{
    using System;
    using System.Collections.Generic;
    using System.Diagnostics.CodeAnalysis;
    using System.Globalization;
    using System.Reflection;
    using System.Text;
    using System.Windows;

    /// <summary>
    /// Helper class to simplify writing if (...) throw ... statements.
    /// </summary>
    public static class ExceptionHelper
    {
        /// <summary>
        /// Throws an <code>ArgumentNullException</code> if the given object parameter is null; does nothing otherwise.
        /// </summary>
        /// <param name="argument">The object parameter to check for null.</param>
        /// <param name="name">The name of the parameter.</param>
        public static void CheckArgumentNotNull(object argument, string name)
        {
            if (argument == null)
            {
                throw new ArgumentNullException(name);
            }
        }

        /// <summary>
        /// Throws a <code>GivingAPresentationException</code> application specific exception if the given condition does not holds; does
        /// nothing otherwise.
        /// </summary>
        /// <param name="condition">The condition to check.</param>
        /// <param name="message">The exception message.</param>
        public static void Check(bool condition, string message)
        {
            if (!condition)
            {
                throw new GivingAPresentationException(message);
            }
        }

        /// <summary>
        /// Shows a dialog box with details about the given exception list.
        /// </summary>
        /// <param name="exceptions">The list of exceptions to show.</param>
        [SuppressMessage("Microsoft.Globalization", "CA1303:Do not pass literals as localized parameters",
            MessageId = "System.Windows.MessageBox.Show(System.String,System.String,System.Windows.MessageBoxButton," +
            "System.Windows.MessageBoxImage)", Justification = "Resources will be used in a future version.")]
        [SuppressMessage("Microsoft.Design", "CA1062:Validate arguments of public methods", MessageId = "0",
            Justification = "Argument is validated by using ExceptionHelper.CheckArgumentNotNull")]
        public static void ShowExceptions(IList<Exception> exceptions)
        {
            ExceptionHelper.CheckArgumentNotNull(exceptions, "exceptions");

            if (exceptions.Count == 0)
            {
                return;
            }

            const string Message = "The following exceptions were raised:{0}";
            StringBuilder sb = new StringBuilder();
            foreach (Exception exception in exceptions)
            {
                sb.Append("\n\n");
                AppendExceptionMessage(sb, exception);
            }

            MessageBox.Show(
                String.Format(CultureInfo.CurrentCulture, Message, sb.ToString()), 
                "Information", 
                MessageBoxButton.OK,
                MessageBoxImage.Information);
        }

        /// <summary>
        /// Appends the exception and details on the inner exception, if any, to the given string.
        /// </summary>
        /// <param name="sb">The string to add exception details to.</param>
        /// <param name="exception">The exception to add.</param>
        private static void AppendExceptionMessage(StringBuilder sb, Exception exception)
        {
            sb.Append(exception.Message);
            if (exception.InnerException != null)
            {
                sb.Append("; caused by: ");
                AppendExceptionMessage(sb, exception.InnerException);
            }

            if (exception.GetType().Equals(typeof(ReflectionTypeLoadException)))
            {
                sb.Append(" LoaderExceptions property item:");
                foreach (Exception loaderException in ((ReflectionTypeLoadException)exception).LoaderExceptions)
                {
                    sb.Append(" ");
                    AppendExceptionMessage(sb, loaderException);
                }
            }
        }
    }
}
